/** * Felinx - Integration link between Felix and Eclipse Copyright (C) 2013 Michiel Vermandel This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.jerry.felinx.runner; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.lang.management.ManagementFactory; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import javax.management.MBeanServer; import javax.management.ObjectName; import org.jerry.felinx.runner.utils.Debug; import org.jerry.felinx.runner.utils.LaunchConfigurator; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.ServiceReference; import org.osgi.framework.launch.Framework; import org.osgi.framework.launch.FrameworkFactory; import org.osgi.service.packageadmin.PackageAdmin; import com.sun.tools.attach.AgentInitializationException; import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.VirtualMachine; public class FrameworkRunner { private Framework framework = null; private static String frameworkLocation = null; public FrameworkRunner() { } /** * @param args * This main is called from org.jerry.felinx.plugin.launch.Launcher */ public static void main(String[] args) { System.out.println("FrameworkRunner v1.0.0.SNAPSHOT"); MBeanServer server = ManagementFactory.getPlatformMBeanServer(); RunnerShell shell = new RunnerShell(); ObjectName shellObjectName; try { shellObjectName = new ObjectName("org.jerry.runner.shell:type=RunnerShell,name=shell"); server.registerMBean(shell, shellObjectName); System.out.println("JMX Shell created."); // System.out.println(loadJMXAgent(9999)); } catch (Exception e) { e.printStackTrace(); } Debug.enabled = true; frameworkLocation = System.getenv("FELIX_HOME"); for (String arg : args) { System.out.println(arg); if (arg.startsWith("FELIX_HOME=")) { // %20 => spaces get replaced by %20 when passing program arguments frameworkLocation = arg.substring(11).replace("%20", " "); } } if (frameworkLocation == null) { System.out.println("Environment variable FELIX_HOME not set!"); frameworkLocation = "C:\\Data\\tools\\felix-framework-4.0.3 - FlowBeans"; } System.out.println("Felinx FrameworkRunner: FELIX HOME = " + frameworkLocation); boolean isDebug = java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments().toString() .indexOf("-agentlib:jdwp") > 0; System.out.println("Debug: " + isDebug); FrameworkRunner runner = new FrameworkRunner(); runner.startFramework(); shell.setFrameworkRunner(runner); } /** * @param aFrameworkLocation * : root of OSGI framework. */ public void startFramework() { try { Map<String, String> config = new HashMap<String, String>(); // LOAD CONFIGURATION FROM FILE: // http://grepcode.com/file/repo1.maven.org/maven2/org.apache.felix/org.apache.felix.main/2.0.3/org/apache/felix/main/Main.java#Main.loadConfigProperties%28%29 config = LaunchConfigurator.loadProperties(frameworkLocation); config.put("felix.cache.rootdir", frameworkLocation); config.put("felix.auto.deploy.dir", "${felix.cache.rootdir}/bundle"); config.put("felix.fileinstall.dir", "${felix.cache.rootdir}/plugins"); framework = getFrameworkFactory().newFramework(config); if (framework != null) { System.out.println("Starting FelixServer from " + frameworkLocation); System.out.println("\nFelixServer..."); System.out.println("======================\n"); framework.init(); framework.start(); // CommandProcessor cmdprc = new CommandProcessor(framework.getBundleContext()); // cmdprc.start(); // check if gogo is ge�nstalleerd boolean gogoShellInstalled = false; for (Bundle bundle : framework.getBundleContext().getBundles()) { if ("org.apache.felix.gogo.shell".equals(bundle.getSymbolicName())) { gogoShellInstalled = true; } } if (!gogoShellInstalled) { System.out.println("WARNING: gogo shell is not installed, cannot handle commands."); } } else { System.err.println("Could not create framework"); } } catch (Exception ex) { System.err.println("Could not create framework: " + ex); ex.printStackTrace(); } } public void stopFramework() { System.out.println("Stopping OSGi Framework..."); try { framework.stop(); framework.waitForStop(0); System.out.println("FelixServer is stopped."); } catch (Exception e) { System.err.println("Could not stop framework: " + e.getMessage()); e.printStackTrace(); } } private static FrameworkFactory getFrameworkFactory() throws Exception { java.net.URL url = FrameworkRunner.class.getClassLoader().getResource( "META-INF/services/org.osgi.framework.launch.FrameworkFactory"); if (url != null) { BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream())); try { for (String s = br.readLine(); s != null; s = br.readLine()) { s = s.trim(); // Try to load first non-empty, non-commented line. if ((s.length() > 0) && (s.charAt(0) != '#')) { Debug.message("> FrameworkFactory class name: " + s); return (FrameworkFactory) Class.forName(s).newInstance(); } } } finally { if (br != null) br.close(); } } throw new Exception("Could not find framework factory."); } public void updateBundle(String aSymbolicName, String aVersion, File aBundleToInstall) throws FileNotFoundException, BundleException { System.out.println("Updating " + aSymbolicName + "... "); /** find bundle */ Bundle bundle = null; if (framework == null || framework.getState() != Bundle.ACTIVE) { System.out.println("Framework not running..."); } else { Bundle[] bundles = framework.getBundleContext().getBundles(); for (Bundle check : bundles) { if (check.getSymbolicName().equals(aSymbolicName) && check.getVersion().toString().equals(aVersion)) { bundle = check; break; } } InputStream stream = new FileInputStream(aBundleToInstall); if (bundle == null) { System.out.println("Bundle does not exist yet. Will install " + aSymbolicName + " " + aVersion + " [" + aBundleToInstall.getAbsolutePath() + "]"); bundle = framework.getBundleContext().installBundle(aBundleToInstall.getAbsolutePath(), stream); } else { bundle.stop(); bundle.update(stream); refreshBundle(bundle, framework.getBundleContext()); } // try { // //sleep a bit? // Thread.sleep(500); // } catch (Exception e) { // //TOO BAD // } // re-get bundle System.out.print("Starting " + aSymbolicName + "..."); boolean started = false; // try bundle-start in loop because refreshBundle (PackageAdmin.refreshPackages keeps a lock on the bundle for a while after // completing the refresh operation) while (!started) { try { bundle.start(); started = true; } catch (Exception e) { try { Thread.sleep(100); } catch (Exception e2) { System.err.println("Could not start bundle "+aSymbolicName+": "+e2.getMessage()); e2.printStackTrace(); break; } } } System.out.println(" started."); } } @SuppressWarnings("deprecation") public void refreshBundle(Bundle changedBundle, BundleContext context) { try { ServiceReference ref = context.getServiceReference(PackageAdmin.class.getName()); PackageAdmin pa = (ref == null) ? null : (PackageAdmin) context.getService(ref); System.out.println("Refreshing bundle " + changedBundle); pa.refreshPackages(new Bundle[] { changedBundle }); } catch (Throwable e) { System.err.println(e.getMessage()); e.printStackTrace(); } } @SuppressWarnings("deprecation") public void refreshDependentBundles(Bundle changedBundle, BundleContext context) { try { long myId = changedBundle.getBundleId(); Dictionary<String, String> headers = changedBundle.getHeaders(); String exported = headers.get("Export-Package") + ","; Bundle[] bundles = context.getBundles(); Set<Bundle> toRefresh = new HashSet<Bundle>(); for (int i = 0; i < bundles.length; i++) { Bundle bundle = bundles[i]; if (bundle.getBundleId() != myId) { if (!bundle.getSymbolicName().startsWith("org.apache")) { Dictionary<String, String> headers2 = bundle.getHeaders(); String imported = headers2.get("Import-Package"); String[] packages = imported.split(","); for (int j = 0; j < packages.length; j++) { String importedPackage = packages[j].trim(); importedPackage = importedPackage.split(";")[0];// no version - for now if (exported.contains(importedPackage)) { toRefresh.add(bundle); } } } } } ServiceReference ref = context.getServiceReference(PackageAdmin.class.getName()); PackageAdmin pa = (ref == null) ? null : (PackageAdmin) context.getService(ref); System.out.println(pa); Bundle[] refreshList = toRefresh.toArray(new Bundle[0]); for (Bundle bundleToRefresh : refreshList) { System.out.println("Refreshing dependend bundle " + bundleToRefresh); } pa.refreshPackages(refreshList); } catch (Throwable e) { System.err.println(e.getMessage()); e.printStackTrace(); } } public static void setConsole(PrintStream ps) { // http://stackoverflow.com/questions/7573188/how-to-capture-console-output-of-eclipse-plugin-with-custom-launch-configuration System.setOut(ps); System.setErr(ps); } public static String loadJMXAgent(int port) throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException { System.setProperty("com.sun.management.jmxremote.port", Integer.toString(port)); String name = ManagementFactory.getRuntimeMXBean().getName(); VirtualMachine vm = VirtualMachine.attach(name.substring(0, name.indexOf('@'))); String lca = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); if (lca == null) { Path p = Paths.get(System.getProperty("java.home")).normalize(); if (!"jre".equals(p.getName(p.getNameCount() - 1).toString().toLowerCase())) p = p.resolve("jre"); File f = p.resolve("lib").resolve("management-agent.jar").toFile(); if (!f.exists()) throw new IOException("Management agent not found"); vm.loadAgent(f.getCanonicalPath(), "com.sun.management.jmxremote"); lca = vm.getAgentProperties().getProperty("com.sun.management.jmxremote.localConnectorAddress"); } vm.detach(); return lca; } }